﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

using libtcod;

namespace Threshold
{
	class Map
	{
		public struct Cell
		{
			public int displayCharacter;
			public TCODColor foregroundColor;
			public TCODColor backgroundColor;
			public bool isTransparent;
			public bool isWalkable;
			public bool isExplored;

			public void SetData(int newDisplayCharacter, TCODColor newForegroundColor, TCODColor newBackgroundColor, bool newIsTransparent, bool newIsWalkable, bool newIsExplored)
			{
				displayCharacter = newDisplayCharacter;
				foregroundColor = newForegroundColor;
				backgroundColor = newBackgroundColor;
				isTransparent = newIsTransparent;
				isWalkable = newIsWalkable;
				isExplored = newIsExplored;
			}

			public void FromNode(XmlNode cellNode)
			{
				string[] rgb;

				displayCharacter = Convert.ToInt32(cellNode.Attributes["displayCharacter"].Value);
				rgb = cellNode.Attributes["foregroundColor"].Value.Split(',');
				foregroundColor = new TCODColor(Convert.ToInt32(rgb[0]), Convert.ToInt32(rgb[1]), Convert.ToInt32(rgb[2]));
				rgb = cellNode.Attributes["backgroundColor"].Value.Split(',');
				backgroundColor = new TCODColor(Convert.ToInt32(rgb[0]), Convert.ToInt32(rgb[1]), Convert.ToInt32(rgb[2]));
				isTransparent = Convert.ToBoolean(cellNode.Attributes["isTransparent"].Value);
				isWalkable = Convert.ToBoolean(cellNode.Attributes["isWalkable"].Value);
				isExplored = Convert.ToBoolean(cellNode.Attributes["isExplored"].Value);
			}

			public XmlNode GetNode(XmlDocument document)
			{
				XmlNode cellNode = document.CreateElement("cell");

				cellNode.Attributes.Append(document.CreateAttribute("displayCharacter"));
				cellNode.Attributes.Append(document.CreateAttribute("foregroundColor"));
				cellNode.Attributes.Append(document.CreateAttribute("backgroundColor"));
				cellNode.Attributes.Append(document.CreateAttribute("isTransparent"));
				cellNode.Attributes.Append(document.CreateAttribute("isWalkable"));
				cellNode.Attributes.Append(document.CreateAttribute("isExplored"));

				cellNode.Attributes["displayCharacter"].Value = displayCharacter.ToString();
				cellNode.Attributes["foregroundColor"].Value = foregroundColor.Red.ToString() + "," + foregroundColor.Green.ToString() + "," + foregroundColor.Blue.ToString();
				cellNode.Attributes["backgroundColor"].Value = backgroundColor.Red.ToString() + "," + backgroundColor.Green.ToString() + "," + backgroundColor.Blue.ToString();
				cellNode.Attributes["isTransparent"].Value = isTransparent.ToString();
				cellNode.Attributes["isWalkable"].Value = isWalkable.ToString();
				cellNode.Attributes["isExplored"].Value = isExplored.ToString();

				return cellNode;
			}

		}

		private int _width;
		private int _height;

		private Cell[,] _cells;

		private int _leftOffset;
		private int _topOffset;

		private TCODMap _tcodMap;

		public Map() : this(80, 50)
		{
		}

		public Map(int width, int height)
		{
			_width = width;
			_height = height;

			_cells = new Cell[_width, _height];
			for (int x = 0; x < _width; x++)
			{
				for (int y = 0; y < _height; y++)
				{
					_cells[x, y].SetData(' ', TCODColor.grey, TCODColor.black, true, true, false);
				}
			}

			_leftOffset = 0;
			_topOffset = 0;
		}

		public int Width { get { return _width; } }
		public int Height { get { return _height; } }

		public void SetData(int x, int y, int newDisplayCharacter, TCODColor newForegroundColor, TCODColor newBackgroundColor, bool newIsTransparent, bool newIsWalkable, bool newIsExplored)
		{
			_cells[x, y].SetData(newDisplayCharacter, newForegroundColor, newBackgroundColor, newIsTransparent, newIsWalkable, newIsExplored);
		}

		public Cell GetCell(int x, int y)
		{
			return _cells[x, y];
		}

		public void Draw(TCODConsole console)
		{
			int mapX;
			int mapY;

			for (int x = 0; x < console.getWidth(); x++)
			{
				for (int y = 0; y < console.getHeight(); y++)
				{
					mapX = x + _leftOffset;
					mapY = y + _topOffset;

					// are we in our bounds?
					if (mapX >= 0 && mapX < _width && mapY >= 0 && mapY < _height)
					{
						console.putCharEx(x, y, _cells[x, y].displayCharacter, _cells[x, y].foregroundColor, _cells[x, y].backgroundColor);
					}
				}
			}
		}

		public void Update(TCODKey key, TCODMouseData mouse, float lastFrameLength)
		{
		}


		public void Load()
		{
			XmlDocument document;
			XmlNode mapNode;

			document = new XmlDocument();
			document.Load(@"map.xml");

			mapNode = document.SelectSingleNode("/map");

			int width = Convert.ToInt32(mapNode.Attributes["width"].Value);
			int height = Convert.ToInt32(mapNode.Attributes["height"].Value);
			int x = 0;
			int y = 0;
			
			_width = width;
			_height = height;

			_cells = new Cell[_width, _height];

			foreach (XmlNode rowNode in mapNode.ChildNodes)
			{
				foreach (XmlNode cellNode in rowNode.ChildNodes)
				{
					_cells[x, y].FromNode(cellNode);
					x++;
				}
				x = 0;
				y++;
			}
		}

		public void Save()
		{
			XmlDocument document;
			XmlNode mapNode;
			XmlNode rowNode;
			XmlNode cellNode;

			document = new XmlDocument();

			mapNode = document.CreateElement("map");
			mapNode.Attributes.Append(document.CreateAttribute("width"));
			mapNode.Attributes.Append(document.CreateAttribute("height"));
			mapNode.Attributes["width"].Value = _cells.GetLength(0).ToString();
			mapNode.Attributes["height"].Value = _cells.GetLength(1).ToString();
			document.AppendChild(mapNode);

			int width = _cells.GetLength(0);
			int height = _cells.GetLength(1);

			for (int y = 0; y < height; y++)
			{
			  rowNode = document.CreateElement("row");
			  for (int x = 0; x < width; x++)
			  {
					cellNode = _cells[x, y].GetNode(document);
					rowNode.AppendChild(cellNode);
			  }
			  mapNode.AppendChild(rowNode);
			}

			document.Save(@"map.xml");
		}




	}
}
